﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using GalaSoft.MvvmLight.Command;
using ZOIL.DataModel;
using ZOIL.Library.Behaviors;

namespace ZOIL.Library.Components
{
    [ViewModelFor(typeof(ZPortalView))]
    public class ZPortalViewModel : ConnectionBaseViewModel
    {
        #region commands

        public RelayCommand ClosePortalCommand { get; private set; }

        #endregion

        #region private fields

        private IDisposable _shapeVisualPropertiesChangedSubscription;

        #endregion

        #region public properties

        #region Model

        public new ZPortal Model
        {
            get
            {
                return base.Model as ZPortal;
            }
            set
            {
                base.Model = value;
            }
        }

        #endregion

        #region GetPortalConnectionPoint

        public Point GetPortalConnectionPoint(Point reference)
        {
            var returnPoint = new Point();
            if (reference.X < Canvas.GetLeft(View))
            {
                returnPoint.X = Canvas.GetLeft(View);
            }
            else if (reference.X < Canvas.GetLeft(View) + View.Width)
            {
                returnPoint.X = reference.X;
            }
            else
            {
                returnPoint.X = Canvas.GetLeft(View) + View.Width;
            }

            if (reference.Y < Canvas.GetTop(View))
            {
                returnPoint.Y = Canvas.GetTop(View);
            }
            else if (reference.Y < Canvas.GetTop(View) + View.Height)
            {
                returnPoint.Y = reference.Y;
            }
            else
            {
                returnPoint.Y = Canvas.GetTop(View) + View.Height;
            }

            return returnPoint;
        }

        #endregion

        #endregion

        #region ctor

        public ZPortalViewModel()
        {
            ClosePortalCommand = new RelayCommand(OnClosePortal);

            ConnectionShape = new RectangleGeometry();
        }

        #endregion

        private void OnClosePortal()
        {
            var rc = DatabaseCollection.Collection;

            var portalShape = Model.PortalShape;
            rc.Remove(portalShape.DatabaseId);
            rc.Remove(((IPersistable)Model).DatabaseId);

            if (_shapeVisualPropertiesChangedSubscription != null)
                _shapeVisualPropertiesChangedSubscription.Dispose();
        }

        protected override void OnElementAdded()
        {
            OnPortalAdded();

            base.OnElementAdded();
        }

        #region event handling

        private void OnPortalAdded()
        {
            var rootCollection = DatabaseCollection.Collection;

            var shape = Model.PortalShape;

            var portalProp = rootCollection.GetVisualProperties(Model.DatabaseId);

            _shapeVisualPropertiesChangedSubscription = Observable.FromEventPattern<PropertyChangedEventArgs>(portalProp, "PropertyChanged")
                                                                  .ObserveOnDispatcher()
                                                                  .Do(_ => UpdateConnectionShape())
                                                                  .Subscribe();

            if (Model.IsMagicLense)
            {
                var shapeProp = rootCollection.GetVisualProperties(shape.DatabaseId);
                shapeProp.Width = shape.Bounds.Width;
                shapeProp.Height = shape.Bounds.Height;
                shapeProp.X = shape.Bounds.Left;
                shapeProp.Y = shape.Bounds.Top;
                shapeProp.TemplateId = "MagicLensePortalShapeTemplate";

                portalProp.Width = shape.Bounds.Width;
                portalProp.Height = shape.Bounds.Height;
                portalProp.X = shape.Bounds.Left;
                portalProp.Y = shape.Bounds.Top;
            }
            else
            {
                if (!Model.IsInitialized && !Model.WasRemotelyCreated)
                {
                    //place portal 100px next to shape
                    portalProp.X = shape.Bounds.Left + shape.Bounds.Width + 100;
                    portalProp.Y = shape.Bounds.Top;
                    Model.IsInitialized = true;
                }
            }

            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(UpdateConnectionShape));
        }

        #endregion
    }
}
